import cv2
import numpy as np
import glob
import os
import sys
import main
import math

sys.path.append(r"E:\SHU\Research Group\LaserVision\LaserVision\Cross_FeaturePointEx\pkgs")
from pkgs import *  # 导入包中 __init__.py指定的模块


# 设置并开启鼠标回调
def draw_point(img):
    #
    def draw_point_callback(event, x, y, flags, param):
        if event == cv2.EVENT_LBUTTONDOWN:
            xy = "(%d,%d)" % (x, y)
            a.append(x)
            b.append(y)
            # 在窗口图像上做标记
            cv2.drawMarker(img, (x, y), (0, 255, 0), cv2.MARKER_CROSS, 10, thickness=1)
            cv2.putText(img, xy, (x, y), cv2.FONT_HERSHEY_PLAIN, 1.0, (0, 255, 255), thickness=1)
            print("[{},{}]".format(a[-1], b[-1]))

    # 设置窗口名字为"image"
    cv2.namedWindow("image")
    # 设置窗口的鼠标回调函数
    cv2.setMouseCallback("image", draw_point_callback)

    # 注意：以上只是设置了窗口内图像的鼠标回调函数，但是并没有产生实际的
    while 1:
        # 回调函数调用并标记图像后，刷新显示窗口图像
        cv2.imshow("image", img)
        # &0xFF是针对64位系统的，32位的需要去掉这里，27即ASCII码，代表ESC
        # &0xFF : 截取低8位
        if cv2.waitKey(20) & 0xFF == 27:
            break

    cv2.destroyAllWindows()


# 获取路径下的所有图片完整路径
def walk_dir(path):
    paths = os.walk(path)
    files = []
    #   文件夹路径、文件夹名称和文件名
    for path, dir_lst, file_lst in paths:
        # 显示所有子目录
        # for dir_name in dir_lst:
        #     print(os.path.join(path, dir_name))
        # 显示目录下所有文件
        for file_name in file_lst:
            print(os.path.join(path, file_name))
            files.append(os.path.join(path, file_name))
    return files


def initial_point_calculate(P1, P2, EP1, EP2):
    # 计算宽度的2个特征点
    EP1X, EP1Y = EP1
    EP2X, EP2Y = EP2
    #
    fp1X, fp1Y = P1  # laserL1  右下
    fp2X, fp2Y = P2  # laserL2  左下

    weld_k = (fp1Y - fp2Y) / (fp1X - fp2X)  # 斜率
    degree = math.atan(weld_k) / 3.1415926 * 180  # 角度

    CornerUp = 90.2  # 90.5
    radUp = (degree + CornerUp) * 3.1415926 / 180
    boundUp_k = math.tan(radUp)  # 传入的是弧度

    CornerDn = 90
    boundDn_k = math.tan(degree + (180 - CornerUp))
    # 倾斜线
    if weld_k != 0:
        weld_b = fp1Y - weld_k * fp1X
        # 绘制垂线
        boundK = -1 / weld_k

        bound_b1 = EP1Y - boundK * EP1X
        init1X = round((weld_b - bound_b1) / (boundK - weld_k))
        init1Y = round(weld_k * init1X + weld_b)

        bound_b2 = EP2Y - boundUp_k * EP2X
        init2X = round((weld_b - bound_b2) / (boundUp_k - weld_k))
        init2Y = round(weld_k * init2X + weld_b)
    else:  # 水平线
        init1X, init2X = EP1X, EP2X
        init1Y, init2Y = fp1Y, fp1Y
    # 将左边的初始点作为初始点返回
    if init1X <= init2X:
        return init1X, init1Y
    else:
        return init2X, init2Y


# 计算初始点坐标
def initial_point_V(img, laser1_, laser2_, EP1, EP2):
    P1mid, P1_1, P1_2 = V.LaserExtract(laser1_, 1)
    P2mid, P2_1, P2_2 = V.LaserExtract(laser2_, 2)
    return initial_point_calculate(P1mid, P2mid, EP1, EP2)


def initial_point_Lap(img, laser1_, laser2_, EP1, EP2):
    P1 = Lap.laser1_Extract(laser1_)
    P2 = Lap.laser2_Extract(laser2_)
    # Com.weldLine(img, P1, EP1, P2, EP2, CrossPoint)
    return initial_point_calculate(P1, P2, EP1, EP2)


def initial_point_SingleBevel(img, laser1_, laser2_, EP1, EP2):
    P1, P1_w = SingleBevel.laser1_Extract(laser1_, start_point1, EP1)
    P2, P2_w = SingleBevel.laser2_Extract(laser2_, start_point2, EP2)
    return initial_point_calculate(P1, P2, EP1, EP2)


def initial_point_Square(img, laser1_, laser2_, EP1, EP2):
    P1mid, P1_1, P1_2 = Square.laser1_Extract(laser1_)  # P1 = [row_gapUp, indexCol1]  # 行，列
    P2mid, P2_1, P2_2 = Square.laser2_Extract(laser2_)
    return initial_point_calculate(P1mid, P2mid, EP1, EP2)


# 调用图像处理算法，返回处理结果(初始点坐标、焊缝类型、[边缘点坐标]、[焊缝特征点])
def process_result(img, weld_type_real):
    # laser1  laser2: 单线全图
    CrossPoint, sp1, sp2, laser1, laser2, regionROI = Com.CrossPointlocation_step2(img, 6)

    # 返回工件边缘点坐标
    EP2, EP1 = Com.edgePointlocation(laser2, laser1)
    (realCol_Up, realRow_Up) = EP2
    (realCol_Dn, realRow_Dn) = EP1  # (x,y)

    # laser1_  laser2_: 边缘点左边的  仅工件上的光条
    laser1_ = laser1[:, :realCol_Dn + 1]
    laser2_ = laser2[:, :realCol_Up + 1]

    # cv.imshow("laser1_", laser1_)
    cv2.imwrite(r"F:\MVS_Data\laser1_.png", laser1_)
    # cv.imshow("laser2_", laser2_)
    cv2.imwrite(r"F:\MVS_Data\laser2_.png", laser2_)
    # cv.waitKey(0)
    # cv.destroyAllWindows()

    # 获取四个区域
    crossRow, crossCol = CrossPoint[1], CrossPoint[0]
    Roi1, _, _, Roi4 = regionROI
    Roi2 = laser2_[0:crossRow, crossCol:]  # Roi2
    Roi3 = laser1_[crossRow:, crossCol:]  # Roi3

    type_encode = (main.gapNum(Roi1, 1), main.gapNum(Roi2, 2), main.gapNum(Roi3, 3), main.gapNum(Roi4, 4))

    weld_type_predicted = "Undefined"
    if type_encode == (0, 0, 0, 0):
        weld_type_predicted = "V"
    elif type_encode == (0, 1, 0, 0) or type_encode == (0, 0, 0, 1):
        weld_type_predicted = "Lap"
    elif type_encode == (1, 0, 0, 0) or type_encode == (0, 0, 1, 0):
        weld_type_predicted = "SingleBevel"
    elif type_encode == (1, 1, 0, 0) or type_encode == (0, 0, 1, 1):
        weld_type_predicted = "Square"

    # 调用图像处理算法
    init_point_x = -1, init_point_y = -1
    if weld_type_real == "V":
        init_point_x, init_point_y = initial_point_V(img, laser1_, laser2_, EP1, EP2)
    elif weld_type_real == "Lap":
        initial_point_Lap(img, laser1_, laser2_, EP1, EP2, CrossPoint)
    elif weld_type_real == "SingleBevel":
        initial_point_SingleBevel()
    elif weld_type_real == "Square":
        initial_point_Square()

    return weld_type_predicted, init_point_x, init_point_y


# 标注所有的图片，并创建对应类型的文件，将标注结果和预测结果保存
def save_result(path):
    files_list = walk_dir(path)
    # 注意：文件列表中含有错误的文件路径，需要对这些错误的文件判断，并保存为error信息
    for files in files_list:
        src = cv2.imread(files)
        src = cv2.resize(src, None, fx=0.4, fy=0.4, interpolation=cv2.INTER_CUBIC)
    # 1. 调用图像处理算法，计算初始点坐标
    # 2. 调用鼠标回调函数，人工标注
    # 3. 保存结果到特定文件中


if __name__ == "__main__":
    # 单个类型图像所在的路径
    V_image_path = r"E:\SHU\Research Group\LaserVisionSensor\MVS_Data\V"
    #

    a = []
    b = []
